home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Garbo
/
Garbo.cdr
/
mac
/
da
/
clpbrdmg.sit
/
programming information
< prev
next >
Wrap
Text File
|
1990-05-24
|
11KB
|
182 lines
The Clipboard Magician would look for components in the file 'Magic Wand'.
The components are of the resource type 'CNVT', the resource name must follow
certain naming convention so that CM understands its content. The first four
characters of the resource name is the data type that the component can work on.
So if the scrap data of type 'ICON' is selected, CM would look for all 'CNVT'
resources with names that start with 'ICON' and displayed them to the user.
'****' is used as the wildcard name, so any component with resource name starting
with '****' is always presented to the user if some scrap data type is selected.
'____' is used to indicate null data where no scrap data is selected. This is
for the components that does not need any input data, but would generate new data
on its own. The rest of the resource name is just the name of the component.
THe component that converts one data type to another has a special naming
convention. The resource name would have a '>' as the fifth character,
followed by new data type name. So the component to convert an 'ICON' to 'PICT'
would have the name 'ICON>PICT'.
The basic model is that each component is a tool for data transformation, a pipe
where certain type of data goes in at one end, and the transformed data comes
out at the other end. The component is not aware that it is processing scrap data.
In fact the components need not be used in the CM environment. I choose the
CM environment because I want to prove it can be done in a very small program.
It can be a much more powerful system if it is put in a richer environment.
The input to the component is the input data type, the input data handle, and
the component would return the output data type and the output data handle.
The 'CNVT' is just a code resource with the entry point at the beginning.
INTERFACE
TYPE
RoutineInfo = RECORD
entryPoint: ProcPtr;
resID: Integer;
parmCount: Integer;
useDefault: Boolean;
END;
RoutineInfoPtr = ^RoutineInfo;
ParmInfo = RECORD
srcType: ResType;
srcHandle: Handle;
dstType: ResType;
dstHandle: Handle;
{ more if necessary }
END;
ParmInfoPtr = ^ParmInfo;
FUNCTION ExtRoutine(myInfoPtr: RoutineInfoPtr; parmPtr:parmInfoPtr):OSErr;
SrcType and srcHandle is the input to the component. The component returns the
data in dstHandle (initialized to NIL before it is called) and type in dstType.
The function returns NoErr if the conversion is successful, otherwise it
returns an error code. If the operation is successful but no data handle is
generated (as in the case where the component just prints the data), then it
should return a NoErr but leaves the dstHandle as NIL.
The RoutineInfo supplies some information that may be useful. ResID is the
resource ID of this code resource. Since a component may need to own resource,
the convention is that an ID range of 32 is assigned to the component. It can
find out its own ID so that it can deduce the ID of the owned resources.
ParmCount is the number of parameters in ParmInfo. Right now it is always 4.
It is put here because it may be possible to use the 'CNVT' components in a
non-CM environment, and then it may be possible to have extra parameters. For
example a text printing module may accept extra parameter as the font and size,
and uses default font and size when parmCount = 4 because no extra parameter
is supplied.
UseDefault means whether to use the default value or to ask the user about it.
In the CM environment UseDefault is false if the command was evoked with the
option key down. So in the text printing module, if UseDefault is true, the
text is printed with certain font and size, if it is false, a font dialog is
used to let the user choose the value.
EntryPoint is the address provided to call other components. If the component
wish to call another component, then it should define the following function
Function GoExec(rtnRsrc: ResType; NamePtr:StrintPtr; parmCount:Integer;
useDefault:Boolean; parmPtr:Ptr; entryPoint:ProcPtr):
OSErr; INLINE $205F, $4E90; {move.l (A7)+, A0; JSR (A0)}
RtnRsrc is the resource type of the component, normally it is 'CNVT'.
'CNVT' resource is visible to the user and will be executed by the user,
If you want to write a component that is shared by several components and yet
not visible to the user, you can put them into 'XRTN' resources. 'XRTN'
resource are like 'CNVT' except there is no naming convention and you
decide what the parmaters are. NamePtr is the name of the componet you want
to call. If you are calling a 'CNVT' component, do not forget that there are
four letters in the front. parmCount, useDefault has the usual meaning.
You make up your own parameter list and use parmPtr to point to it. Remember
that if you are calling a XRTN, then the parameter record no longer need to
be of the type ParmInfo, that is why parmPtr is a Ptr rather than a ParmInfoPtr.
entryPoint is just the address provided in routineInfo and GoExec just jsr to it.
Also noted that the call may be to an external routine as well as to an
internal routine since it is up to the dispatcher in CM. However, the current
implementation of CM has no internal call back routine so all calls would be
dispatched to external components.
'CNVT' component may have a resource 'CNV!' with the same ID and the same data
format as 'STR ', the string is a simple description of the component and
will be displayed when the user choose "About this command" from the menu.
******************************************************************************
In version 0.55, you may return a data type name 'scrp' which has the same format
as scrap data, i.e. Type name followed by long word data length, followed by the
data padded to even bytes, then the next type etc. The DA would break up the data
and put all of them on to the scrap. Be aware of the fact the specification of the
clipboard magician still need improvement and expect such evolutionary changes in the
future.
I have also included a sample program to show how a convertor looks like. For
those of you working with Think Pascal, I have also include a simulator that
let you dubug a CNVT code resource as an ordinray routine rather than as a code
resource so that you can use all the dubug facilites of Think. This is like the DA
shell in Think. In fact all the components release after version 0.5 are written this way.
There are two constants you need to specify for every new CNVT that you are going to
write. The first is the type of data it can handle (resource name/****/____). If you
intend to use resources you also need to specify the resource base ID.
If you intend to call other code resources you should make a copy of the Magic Wand
and use that file as your resource file in your development process. You may use the
Magic Wand file directly if you do not intend to call up the Clipboard Magican DA
during your debug process. However my own experience is that it is useful to be able
to call up the DA. The simulator is for testing purpose and does not operates like
the DA. Here the components do not work on the data from the scrap directly. The
program maintains a list of data objects (which you can cut/copy/paste to the scrap),
the component will work on the data object selected and the result will be added to
the list of data objects.
*****************************************************************************
Starting from version 0.61, there are a number of changes.
First, there is no longer a 'XRTN' type of resource. If you want a CNVT that is not
visiable to the user, give it the datatype of ' ', since there is no such datatype
it would be not be visiable.
The meaning of parmCount has been changed slightly, now a ResType and the data handle
together is treated as one parameter and every parameter must be of that form, i.e. typed.
So most of the time expect a parmCount of 2.
It was mentioned in the last release that there is a new data type called 'scrp' for a
list of data but it is subjected to change, well, it has been changed in this version.
It is now replaced by 'list' with a different structure. We need not know about the
exact structure. Rather you can call a CNVT to make a list. The paraminfo that you passed
to the CNVT called ' MakeList' is
ResType of first item in list
handle to first item in list
ResType of result, i.e 'list'
handle to the list
ResType of 2nd item in list
handle to 2nd item in list
..
ResType of Nth item in list
handle to Nth item in list
and parmCount is N.
One problem with call by name is that it is not easily localizable. Procedure EnglishNameA
may call procedure EnglishNameB. In France they are renamed FrenchNameA and FrenchNameB.
However procedure A is still calling EnglishNameB in its code and hence it cannot be located.
I had a clean solution in verison 0.62 but I have to removed it for other consideration.
Now each resource is encouraged to be assigned an 8 byte name which will be the resource
name of the CNV! resource and will be language independent. For reason that will be clear in
the future, the first 4 byte of the 8 byte name should be 'MAGI', One resource should call another
by the 8 byte name (using a resource type of 'CNV!') to avoid localization problem. The old
method of calling by full name would still work.
So to call another code resource with signature 'MAGIABCD'
err := GoExec('CNV!', 'MAGIABCD', parmCount, useDefault, parmPtr, entryPoint);
An important feature of version 0.64 is that any type of code resource may be used provided
there is an adopter for it. The adopter is a CNVT called ' DoXXXX' where XXXX is the
data type. So if you want to use XCMD, you need to have a CNVT called ' DoXCMD' that would
translate CNVT calling convention to XCMD calling convention. ' DoXXXX' CNVT will get
a parameter block with parmCount = 3, the first parameter is still the source data, and the
second parameter is still for storing the result, the third parameter is a handle to the
resource handle. So when you called 'TEXTFlash', the text is in the srcData, the Flash XCMD
resource handle is in the third parameter, ' DoXCMD' would translate the text data into a
zero terminated string that Flash expects, then it would lock down Flash and call it, then
in the case of an XFCN, it would take the function result which is a zero terminated string
and change it back to text and then put in back as the second parameter. This is how you can
introduce new code resource type to CM.
The Think Pascal shell program has been updated to reflect these changes.